package com.data_structure_algorithm.data_structure.linked;

import java.util.Objects;

/**
 * @author 何章怀晓 hezhanghuaixiao
 * @version V1.0
 * @desc  简单链表
 */
public class SimpleLinked {

  //头结点
  private CharacterNode header = new CharacterNode(0, "header", "header");


  public void add(CharacterNode element) {
    // 必须先找到插入节点的前节点

    CharacterNode temp = header;
    //判空
    if (Objects.isNull(temp)) {
      System.out.println("头节点为空");
      return;
    }
    boolean flag = false;

    while (true) {
      if (temp.getNext() == null) {
        break;
      }

      if (temp.getNext().getId() > element.getId()) {
        break;
      } else if (temp.getNext().getId() == element.getId()) {
        flag = true;
        break;
      }

      temp = temp.getNext();
    }

    if (flag) {
      System.out.println("id重复");
      return;
    }

    element.setNext(temp.getNext());
    temp.setNext(element);

  }

  public void update(CharacterNode element) {

    if (Objects.isNull(header)) {
      System.out.println("linked is null !");
      return;
    }
    //根据编号修改信息
    CharacterNode temp = header;

    while (true) {
      //虚假编号
      if (temp.getNext() == null) {
        System.out.println("此英雄不存在...");

        return;
      }

      if (temp.getNext().getId() == element.getId()) {
        //操作
        CharacterNode next = temp.getNext();
        next.setName(element.getName());
        next.setNickname(element.getNickname());

        System.out.println("修改完成");
        return;
      }

      temp = temp.getNext();
    }
  }

  public void delete(int id) {

    CharacterNode temp = header;

    if (Objects.isNull(temp)) {
      System.out.println("linked is null !");
      return;
    }
    if (temp.getNext() == null) {
      return;
    }

    while (true) {
      //找到最后了
      if (temp.getNext() == null) {
        System.out.println("查无此人");
        return;
      }

      if (temp.getNext().getId() == id) {
        break;
      }

      temp = temp.getNext();
    }

    //操作

    temp.setNext(temp.getNext().getNext());
  }


  public void bianli() {
    //临时节点
    CharacterNode temp = header;

    //判断,这里不会为null，头结点已经初始化过了
    if (Objects.isNull(temp)) {
      System.out.println("链表为空");
      return;
    }

    for (; ; ) {
      //判断是都有节点
      if (temp.getNext() == null) {

        return;
      }

      System.out.println(temp.getNext().toString());
      //后移
      temp = temp.getNext();
    }


  }


  public void bianli2(CharacterNode node) {

    //判断,这里不会为null，头结点已经初始化过了
    if (Objects.isNull(node)) {
      System.out.println("链表为空");
      return;
    }

    for (; ; ) {
      //判断是都有节点
      if (node.getNext() == null) {

        return;
      }

      System.out.println(node.getNext().toString());
      //后移
      node = node.getNext();
    }


  }


  //求单链表的有效节点个数
  public int getNum() {
    CharacterNode temp = header;
    int num = 0;
    while (true) {
      if (temp.getNext() == null) {
        break;
      }
      temp = temp.getNext();
      num++;
    }
    return num;
  }

  //查找倒数第N个节点
  public CharacterNode findNode(int index) {
    //查找导数第num个节点
    //步骤
    //先遍历确定有多少节点
    int num = getNum();
    //总结点数-n
    int tail = num - index;
    //遍历到总结点数-n个就行
    CharacterNode temp = header;
    int flag = 0;
    while (true) {
      if (flag == tail + 1) {
        break;
      }

      temp = temp.getNext();
      flag++;
    }

    return temp;


  }


  public CharacterNode flip() {
    CharacterNode headNode = header;//当前节点

    if (headNode == null || headNode.getNext() == null || headNode.getNext().getNext() == null) {
      throw new RuntimeException("is null");
    }

    CharacterNode curr = headNode.getNext(); //当前节点的实际首节点

    CharacterNode next = null;//当前节点的前一个节点，反转后变为当前节点的后节点

    CharacterNode newNode = new CharacterNode();//新链表

    while (curr != null) {
      //先将当前节点下个节点取出
      next = curr.getNext();//即下次遍历的当前节点

      curr.setNext(newNode.getNext());//新链表当前下个节点变为当前节点的下节点，意思当前节点插队了

      //将当前节点放在链表最前端
      newNode.setNext(curr);

      curr = next;//后移


    }

    //将之前头结点指向当前新节点的下个节点即可
    headNode.setNext(newNode.getNext());







/*
    //问题：反向指针，那么当前节点之前的next就断了，需要在反转之前，将之前节点的next节点临时保存
    CharacterNode preNode = null;//代表旧链表的 当前节点的前节点，因为反转后，之前的前节点会变为后节点

    while (headNode != null) {
      CharacterNode NowNextNode = headNode.getNext();//当前节点的后节点
      //将当前节点的下一个指向之前当前节点的上一个
      headNode.setNext(preNode);

      preNode = headNode;//为下次循环作准备  当前节点变为下一次循环的当前节点的上一个节点

      headNode = NowNextNode;//下次循环的当前节点变为现在循环的下个节点


    }*/

    return headNode;


  }


  public CharacterNode flip2() {
    CharacterNode headNode = header;

    //判空
    if (headNode == null || headNode.getNext() == null || headNode.getNext().getNext() == null) {
      throw new RuntimeException("链表为空或链表只有一个元素无需反转");
    }

    //目的：遍历链表，将每次取出的数据放在链表的最前端-->插队

    CharacterNode curr = headNode.getNext();//当前节点

    CharacterNode next = null;

    //建立新节点
    CharacterNode newNode = new CharacterNode();

    while (curr != null) {//如果当前节点不为null 注：当前节点不断变化

      //先取出当前节点的下个节点
      next = curr.getNext();

      //插队  当前链表的下个节点，变为当前节点的下个节点
      //如果当前进来的是首节点，那么newNode.next将为null，因为此时newNode是空的，首节点反转后，变为尾节点
      curr.setNext(newNode.getNext());


      //当前链表的下节点变为当前节点
      newNode.setNext(curr);

      //指针后移，为下次循环作准备
      curr = next;

    }


    headNode.setNext(newNode.getNext());

    return headNode;
  }


  public static void main(String[] args) {
    SimpleLinked simpleLinked = new SimpleLinked();
    simpleLinked.add(new CharacterNode(2, "卢俊义", "玉麒麟"));
    simpleLinked.add(new CharacterNode(4, "公孙胜", "入云龙"));
    simpleLinked.add(new CharacterNode(1, "宋江", "呼保义"));
    simpleLinked.add(new CharacterNode(3, "wuyong", "zhiduoxing"));
    simpleLinked.add(new CharacterNode(6, "linchong", "baozitou"));
    simpleLinked.add(new CharacterNode(9, "huarong", "xiaoliguang"));

    simpleLinked.bianli();//这里是按照添加顺序
    System.out.println("反转");
    CharacterNode flip = simpleLinked.flip2();
    simpleLinked.bianli2(flip);
  }


}


//节点Node
class CharacterNode {

  //数据属性
  private Integer id;

  private String name;

  private String nickname;

  private CharacterNode next;

  public CharacterNode(Integer id, String name, String nickname) {
    this.id = id;
    this.name = name;
    this.nickname = nickname;
  }

  public CharacterNode() {
  }

  public Integer getId() {
    return id;
  }

  public void setId(Integer id) {
    this.id = id;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getNickname() {
    return nickname;
  }

  public void setNickname(String nickname) {
    this.nickname = nickname;
  }

  public CharacterNode getNext() {
    return next;
  }

  public void setNext(CharacterNode next) {
    this.next = next;
  }

  @Override
  public String toString() {
    return "CharacterNode{" +
        "id=" + id +
        ", name='" + name + '\'' +
        ", nickname='" + nickname + '\'' +
        '}';
  }
}
